package main

import "fmt"

// 接口的定义:定义规则、定义规范, 定义某种能力:
type SayHello interface {
	// 声明没有实现的方法
	sayHello()
}

// 接口的实现:定义一个结构体
// 中国人
type Chinese struct {
	name string
}
// 实现接口的方法,具体的实现
func (chinese Chinese) sayHello() {
	fmt.Println("你好")
}
// 中国人有扭秧歌的方法
func (chinese Chinese) niuYangGe() {
	fmt.Println("东北文化-扭秧歌")
}

// 接口的实现:定义一个结构体
// 美国人
type American struct {
	name string
}
// 实现接口的方法,具体的实现
func (american American) sayHello() {
	fmt.Println("hi")
}
// 美国人跳disco
func (american American) disco() {
	fmt.Println("野狼disco")
}

// 定义函数,用来接收各国人打招呼的函数,接收具备SayHello接口的能力的变量
func greet(s SayHello) { // s可以通过上下文来识别具体是什么类型的实例,就体现出多态
	s.sayHello()
	// 断言: 看s是否可以转成Chinese类型,并赋给变量chinese
	//chinese, flag := s.(Chinese)
	//if flag {
	//	chinese.niuYangGe()
	//} else {
	//	fmt.Println("美国人不会扭秧歌")
	//}

	// 第二种写法
	//if chinese, flag := s.(Chinese); flag {
	//	chinese.niuYangGe()
	//} else {
	//	fmt.Println("美国人不会扭秧歌")
	//}

	// 第三种写法,如果美国人结构体也有不同的方法
	switch s.(type) {
	case Chinese:
		ch := s.(Chinese)
		ch.niuYangGe()
	case American:
		am := s.(American)
		am.disco()
	}
}

func main() {
	// 创建中国人
	c := Chinese{}
	a := American{}
	greet(c)
	greet(a)

}
